home *** CD-ROM | disk | FTP | other *** search
-
- /* @(#)io.c 1.5 92/04/16
- *
- * File handling routines used by the popi program.
- *
- * Popi was originally written by Gerard J. Holzmann - AT&T Bell Labs.
- * This version is based on the code in his Prentice Hall book,
- * "Beyond Photography - the digital darkroom," ISBN 0-13-074410-7,
- * which is copyright (c) 1988 by Bell Telephone Laboratories, Inc.
- *
- * Permission is given to distribute these extensions, as long as these
- * introductory messages are not removed, and no monies are exchanged.
- *
- * No responsibility is taken for any errors or inaccuracies inherent
- * either to the comments or the code of this program, but if reported
- * (see README file) then an attempt will be made to fix them.
- */
-
-
- #include <stdio.h>
- #include <string.h>
- #include <errno.h>
- #include <ctype.h>
- #include "popi.h"
- #include "libpbm.h"
-
- #if unix || AMIGA
- #define RMODE "r"
- #define WMODE "w"
- #else /* ! (unix || AMIGA) */
- #define RMODE "rb"
- #define WMODE "wb"
- #endif /* unix || AMIGA */
-
- #if defined(unix)
- static bool IsPopen = FALSE ;
- #endif /* unix */
-
- int nimages = 2 ;
-
-
- pixel_t **
- ImgAlloc(xsize, ysize, ncolors)
- int xsize, ysize, ncolors ;
- {
- int color ;
- pixel_t **img ;
-
- noerr = TRUE ;
- img = (pixel_t **)
- LINT_CAST(Emalloc((unsigned) ncolors * sizeof(pixel_t *))) ;
- if (img == 0) return((pixel_t **) 0) ;
- for (color = 0; color < ncolors; color++)
- img[color] = (pixel_t *)
- LINT_CAST(Emalloc((unsigned) xsize * ysize * sizeof (pixel_t))) ;
-
- if (!noerr)
- {
-
- /* Run out of memory; free what we have allocated */
-
- for (color = 0; color < ncolors; color++)
- if (img[color]) free((char *) img[color]) ;
- return((pixel_t **) 0) ;
- }
- return(img) ;
- }
-
-
- void
- ImgFree(img)
- struct SRC *img ;
- {
- int color ;
-
- free(img->str) ;
- img->str = (char *) 0 ;
-
- for (color = 0; color < img->ncolors; color++)
- free((char *) img->pix[color]) ;
- free((char *) img->pix) ;
- img->pix = (pixel_t **) NULL ;
- }
-
-
- void
- Efclose(stream)
- FILE *stream ;
- {
- #ifdef unix
- if (IsPopen)
- {
- PCLOSE(stream) ;
- IsPopen = FALSE ;
- }
- else
- #endif /* unix */
- FCLOSE(stream) ;
- }
-
-
- FILE *
- EfopenR(filename)
- char *filename ;
- {
- FILE *istr ;
- #if unix
- FILE *popen() ;
- #endif /* unix */
-
- DEBUG((Debug, "EfopenR(%s)\n", filename)) ;
- if ((istr = fopen(filename, RMODE)) != NULL) return(istr) ;
-
- #if unix
- if (errno == ENOENT)
- {
- char buf[MAXPATHLEN] ;
-
- /* First see if the compressed file exists and is readable */
-
- SPRINTF(buf, "%s.Z", filename) ;
- if ((istr = fopen(buf, "r")) != NULL)
- {
-
- /* OK - it's there */
-
- FCLOSE(istr) ;
- SPRINTF(buf, "zcat %s", filename) ;
- DEBUG((Debug, "popen(%s)\n", buf)) ;
- if ((istr = popen(buf, "r")) != NULL)
- {
- IsPopen = TRUE ;
- return(istr) ;
- }
- }
- }
- #endif /* unix */
-
- SPRINTF(ErrBuf, "Can't read file '%s'", filename) ;
- error(ERR_SYS) ;
- return(NULL) ;
- }
-
-
- FILE *
- EfopenW(filename)
- char *filename ;
- {
- FILE *ostr ;
- #ifdef unix
- FILE *popen() ;
- #endif /* unix */
-
- DEBUG((Debug, "EfopenW(%s)\n", filename)) ;
-
- #ifdef unix
- if (*filename == '|')
- {
- ++filename ;
-
- if ((ostr = popen(filename, "w")) == NULL)
- {
- SPRINTF(ErrBuf, "Can't run command '%s'", filename) ;
- error(ERR_SYS) ;
- }
- IsPopen = TRUE ;
- return ostr ;
- }
- #endif /* unix */
-
- if ((ostr = fopen(filename, WMODE)) == NULL)
- {
- SPRINTF(ErrBuf, "Can't write file '%s'", filename) ;
- error(ERR_SYS) ;
- }
- return(ostr) ;
- }
-
-
- void
- do_ioerror(fd, filename, direction, row)
- FILE *fd ;
- char *filename, *direction ;
- int row ;
- {
- if (ferror(fd))
- {
- SPRINTF(ErrBuf, "File '%s' %s error on row %d",
- filename, direction, row) ;
- error(ERR_SYS) ;
- FCLOSE(fd) ;
- return ;
- }
-
- SPRINTF(ErrBuf, "File '%s' insufficient data at row %d", filename, row) ;
- error(0) ;
- }
-
-
- void
- adjust_image(old, newp, nwidth, ncolors)
- struct SRC *old ;
- pixel_t **newp ;
- int nwidth, ncolors ;
- {
- int c, n, o, x, y ;
-
- if (old->ncolors == 1)
- {
- if (ncolors == 1)
- for (y = 0; y < old->height; y++)
- {
- o = y * old->width ;
- n = y * nwidth ;
- for (x = 0; x < old->width; x++)
- newp[0][n+x] = old->pix[0][o+x] ;
- }
- else
- for (y = 0; y < old->height; y++)
- {
- o = y * old->width ;
- n = y * nwidth ;
- for (x = 0; x < old->width; x++)
- newp[0][n+x] = newp[0][n+x] = newp[0][n+x] = old->pix[0][o+x] ;
- }
- }
- else
- for (c = 0; c < old->ncolors; c++)
- {
- o = y * old->width ;
- n = y * nwidth ;
- for (x = 0; x < old->width; x++)
- newp[c][n+x] = old->pix[c][o+x] ;
- }
- }
-
-
- void
- getpix(filename, imgname, started)
- char *filename ; /* File name */
- char *imgname ; /* Image name */
- int started ;
- {
- FILE *fd ;
- struct SRC *img ; /* Pointer into Images */
- struct SRC *unused = (struct SRC *) 0 ; /* First unused slot */
- char *p ;
- char *rem ;
- int len ;
- pixel_t **tmpOldp, **tmpNewp ;
- int height, mask, ncolors, off, width, x,y ;
-
- extern int pm_iserror ;
-
- int format ;
- pixval maxval ;
- gray *grayrow ;
- pixel *pixelrow ;
-
- len = strlen(filename) ;
- if (len > 2 && !strncmp(&filename[len-2], ".Z", 2)) filename[len-2] = '\0' ;
-
- if ((fd = EfopenR(filename)) == NULL) return ;
- pm_iserror = FALSE ;
- ppm_readppminit(fd, &width, &height, &maxval, &format) ;
-
- if (format == PBM_FORMAT || format == RPBM_FORMAT ||
- format == PGM_FORMAT || format == RPGM_FORMAT)
- {
- ncolors = 1 ;
- grayrow = pgm_allocrow(width) ;
- }
- else if (format == PPM_FORMAT || format == RPPM_FORMAT)
- {
- ncolors = 3 ;
- pixelrow = ppm_allocrow(width) ;
- }
- else if (format == OLD_POPI_FORMAT) ncolors = 1 ;
-
- if (imgname == 0 || *imgname == '\0')
- {
- imgname = filename ;
-
- /*
- * Use the basename of the filename for the image name. If this results in a
- * non-valid image name, they'll just have to use the $n equivalent. It's not
- * our business to go transforming names.
- */
-
- /* Find last '/' in string */
-
- for (p = rem = imgname; *p; ++p)
- if (*p == '/' && p[1] != '\0') rem = p + 1 ;
-
- imgname = rem ;
- }
-
- /* See if the named image already exists */
-
- for (img = Images; img != &Images[nimages]; ++img)
- {
- if (img->str && strcmp(img->str, imgname) == 0) break ;
-
- if (img->pix == (pixel_t **) NULL && unused == (struct SRC *) NULL)
- unused = img ;
- }
-
- if (img == &Images[nimages])
- {
-
- /* Named image doesn't exist. Allocate a new image. */
-
- if (unused == (struct SRC *) 0) img = &Images[nimages++] ;
- else img = unused ;
-
- if ((img->pix = ImgAlloc(width, height, ncolors)) == 0 ||
- (img->str = (char *)
- Emalloc((unsigned int) (strlen(imgname)+1))) == 0)
- return ;
-
- STRCPY(img->str, imgname) ;
- }
- else if (img->width != width || img->height != height ||
- img->ncolors != ncolors)
- { /* Existing image has changed size or depth. */
- ImgFree(img) ;
- if ((img->pix = ImgAlloc(width, height, ncolors)) == 0 ||
- (img->str = (char *)
- Emalloc((unsigned int) (strlen(imgname)+1))) == 0)
- return ;
-
- STRCPY(img->str, imgname) ;
- }
-
- img->width = width ;
- img->height = height ;
- img->ncolors = ncolors ;
- img->Xalloc = width ;
-
- /* Read in the image. */
-
- for (y = 0; y < height; y++)
- {
- mask = (signed_io) ? 0x80 : 0x00 ;
- if (format == PBM_FORMAT || format == RPBM_FORMAT ||
- format == PGM_FORMAT || format == RPGM_FORMAT)
- {
- pgm_readpgmrow(fd, grayrow, width, maxval, format) ;
- if (pm_iserror == TRUE)
- {
- do_ioerror(fd, filename, "read", y) ;
- return ;
- }
- off = y * width ;
- for (x = 0; x < width; x++)
- img->pix[0][off+x] = (char) (grayrow[x] ^ mask) ;
- }
- else if (format == PPM_FORMAT || format == RPPM_FORMAT)
- {
- ppm_readppmrow(fd, pixelrow, width, maxval, format) ;
- if (pm_iserror == TRUE)
- {
- do_ioerror(fd, filename, "read", y) ;
- return ;
- }
- off = y * width ;
- for (x = 0; x < width; x++)
- {
- img->pix[0][off+x] = pixelrow[x].r ^ mask ;
- img->pix[1][off+x] = pixelrow[x].g ^ mask ;
- img->pix[2][off+x] = pixelrow[x].b ^ mask ;
- }
- }
- else if (format == OLD_POPI_FORMAT)
- {
- if (fread((char *) img->pix[0][y*width], 1, width, fd) <= 0)
- {
- do_ioerror(fd, filename, "read", y) ;
- return ;
- }
- }
- }
-
- if (format == PGM_FORMAT || format == RPGM_FORMAT ||
- format == PGM_FORMAT || format == RPGM_FORMAT)
- pgm_freerow(grayrow) ;
- else if (format == PPM_FORMAT || format == RPPM_FORMAT)
- ppm_freerow(pixelrow) ;
- Efclose(fd) ;
-
- /* Set the size of the pictures "old" and "new" to the size of the picture
- * just read. Note: this cannot be :undo(ne). If sizes have changed, throw
- * away the polar-table (if any).
- */
- if (((CurOld->width != width) || (CurOld->height != height)) && (avals))
- {
- FREE((char *) avals) ;
- FREE((char *) rvals) ;
- avals = NULL ;
- rvals = NULL ;
- }
- CurOld->width = width ;
- CurOld->height = height ;
- CurNew->width = width ;
- CurNew-> height = height ;
-
- /* Check to see if this new image is larger in size or greater in depth than
- * the current "max" image. If so, then the "new" and "old" images need to
- * be reallocated, copying across the current information.
- */
-
- if ((ncolors > colors) || (width > Xsize) || (height > Ysize))
- {
- tmpOldp = ImgAlloc((width > Xsize) ? width : Xsize,
- (height > Ysize) ? height : Ysize, ncolors) ;
- adjust_image(CurOld, tmpOldp,
- (width > Xsize) ? width : Xsize, ncolors) ;
-
- tmpNewp = ImgAlloc((width > Xsize) ? width : Xsize,
- (height > Ysize) ? height : Ysize, ncolors) ;
- adjust_image(CurNew, tmpNewp,
- (width > Xsize) ? width : Xsize, ncolors) ;
-
- ImgFree(CurOld) ;
- ImgFree(CurNew) ;
-
- CurOld->pix = tmpOldp ; /* Create new "old" image. */
- CurOld->str = Emalloc((unsigned int) (strlen("old")+1)) ;
- STRCPY(CurOld->str, "old") ;
- CurOld->width = width ;
- CurOld->height = height ;
- CurOld->ncolors = ncolors ;
-
- CurNew->pix = tmpNewp ; /* Create new "new" image. */
- CurNew->str = Emalloc((unsigned int) (strlen("new")+1)) ;
- STRCPY(CurNew->str, "new") ;
- CurNew->width = width ;
- CurNew->height = height ;
- CurNew->ncolors = ncolors ;
-
- if (width > Xsize) Xsize = width ;
- if (height > Ysize) Ysize = height ;
- if (ncolors > colors) colors = ncolors ;
- CurOld->Xalloc = Xsize ;
- CurNew->Xalloc = Xsize ;
-
- if (colors == 3)
- {
- if (ntsc != NULL) FREE((char *) ntsc) ;
- ntsc = (pixel_t *) Emalloc((unsigned) Xsize * sizeof(pixel_t)) ;
- }
- if (started == TRUE) disp_resize(Xsize, Ysize) ;
- }
- }
-
-
- void
- putpix(into, filename)
- struct SRC *into ; /* Work buffer */
- char *filename ; /* File name */
- {
- FILE *fd ;
- int mask, off, x, y ;
-
- extern int pm_iserror ;
-
- int format ;
- pixval maxval ;
- gray *grayrow ;
- pixel *pixelrow ;
-
- if ((fd = EfopenW(filename)) == NULL) return ;
- pm_iserror = FALSE ;
- maxval = 255 ;
- if (into->ncolors == 1)
- {
- format = RPGM_FORMAT ;
- if (oldfmt != TRUE)
- pgm_writepgminit(fd, into->width, into->height, maxval) ;
- grayrow = pgm_allocrow(into->width) ;
- }
- else if (into->ncolors == 3)
- {
- format = RPPM_FORMAT ;
- ppm_writeppminit(fd, into->width, into->height, maxval) ;
- pixelrow = ppm_allocrow(into->width) ;
- }
-
- /* Write out the image. */
-
- for (y = 0; y < into->height; y++)
- {
- mask = (signed_io) ? 0x80 : 0x00 ;
- if (format == RPGM_FORMAT)
- {
- off = y * into->Xalloc ;
- for (x = 0; x < into->width; x++)
- grayrow[x] = into->pix[0][off+x] ^ mask ;
- pgm_writepgmrow(fd, grayrow, into->width, maxval) ;
- if (pm_iserror == TRUE)
- {
- do_ioerror(fd, filename, "write", y) ;
- return ;
- }
- }
- else if (format == RPPM_FORMAT)
- {
- off = y * into->Xalloc ;
- for (x = 0; x < into->width; x++)
- {
- pixelrow[x].r = into->pix[0][off+x] ^ mask ;
- pixelrow[x].g = into->pix[1][off+x] ^ mask ;
- pixelrow[x].b = into->pix[2][off+x] ^ mask ;
- }
- ppm_writeppmrow(fd, pixelrow, into->width, maxval) ;
- if (pm_iserror == TRUE)
- {
- do_ioerror(fd, filename, "write", y) ;
- return ;
- }
- }
- }
-
- if (format == RPGM_FORMAT) pgm_freerow(grayrow) ;
- else if (format == RPPM_FORMAT) ppm_freerow(pixelrow) ;
-
- Efclose(fd) ;
- }
-
-
- void
- prntimg(imgname, im)
- char *imgname ;
- struct SRC *im ;
- {
- int i, len ;
-
- len = strlen(imgname) ;
- for (i = 0; i < 40; ++i)
- {
- PRINTF("%c", (i < len) ? imgname[i] : ' ') ;
- if (LogStr)
- FPRINTF(LogStr, "%c", (i < len) ? imgname[i] : ' ') ;
- }
- PRINTF("\t[%d,%d] (%s)\n", im->width, im->height,
- (im->ncolors == 1) ? "gray" : "color") ;
- if (LogStr)
- FPRINTF(LogStr, "\t[%d,%d] (%s)\n", im->width, im->height,
- (im->ncolors == 1) ? "gray" : "color") ;
- }
-
-
- void
- showfiles()
- {
- struct SRC *img ;
- int j ;
- char namestr[MAXLINE] ;
-
- PRINTF("\t\tRange error handling: %s\n", (rng_policy == CUT) ? "cut" :
- (rng_policy == MINMAX) ? "minmax" : "wrap") ;
- if (LogStr)
- FPRINTF(LogStr, "\t\tRange error handling: %s\n",
- (rng_policy == CUT) ? "cut" :
- (rng_policy == MINMAX) ? "minmax" : "wrap") ;
- prntimg("-previous-", CurNew) ;
- prntimg("-CURRENT-", CurOld) ;
- for (j = 1, img = &Images[2]; j < nimages - 1; ++img, ++j)
- {
- if (img->str)
- {
- SPRINTF(namestr, "$%d = %s", j, img->str) ;
- prntimg(namestr, img) ;
- }
- }
- }
-